package com.stylefeng.guns.modular.netcar.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.google.common.collect.Maps;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.common.Tools.Result;
import com.stylefeng.guns.core.model.CommonKeyValue;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.support.DateTimeKit;
import com.stylefeng.guns.core.util.AliMsgUtils;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.modular.netcar.dao.OrderInfMapper;
import com.stylefeng.guns.modular.netcar.model.*;
import com.stylefeng.guns.modular.netcar.service.*;
import com.stylefeng.guns.modular.system.service.ISysSerialnumInfService;
import com.stylefeng.guns.modular.transcapacitymag.model.PreOrderInf;
import com.stylefeng.guns.modular.transcapacitymag.service.IPreOrderInfService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.inject.Inject;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 订单信息 Service 实现
 * @author sasazaixian
 * @Date 2018-10-25 18:11
 */
@Service
@Slf4j
public class OrderInfServiceImpl extends ServiceImpl<OrderInfMapper,OrderInf> implements IOrderInfService {

    @Resource
    private OrderInfMapper orderInfMapper;
    @Autowired
    private IVehiclePriceTypeService vehiclePriceTypeService;
    @Autowired
    private IOrderLineService orderLineService;
    @Autowired
    private ILineTimeSlotService lineTimeSlotService;
    @Autowired
    private ISysSerialnumInfService sysSerialnumInfService;
    @Autowired
    private ILineDispatchPsnService lineDispatchPsnService;
    @Autowired
    private IOrderUserRelationService orderUserRelationService;
    @Inject
    private IPreOrderInfService preOrderInfService;
    @Inject
    private ITaskInfService taskInfService;
    @Inject
    private ITaskOrderService taskOrderService;
    /**保存失败原因*/
    private static ThreadLocal<String> msg=new ThreadLocal<>();

    @Value("${weifutong.type}")
    private String reType;

    @Value("${spring.validMinuteOrder}")//#订单未付款时预留票的时间 过后自动取消
    private String validMinuteOrder;

    @Value("${spring.clientHotLine}")//#客户服务热线
    private String clientHotLine;

    @Value("${weifutong.refund_url}")
    private String REFUND_URL;
    @Value("${weifutong.refund_method}")
    private String method;

    /**
     * 删除订单信息
     *
     * @param orderInf
     * @return
     */
    @Transactional
    public int deleteOrderInf(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null) {
            throw new RuntimeException("参数不全！");
        }
        List<OrderInf> list = orderInfMapper.selectListOrderInf(orderInf);
        for (OrderInf order : list) {
            if (order.getCiState().equals("2")) {
                throw new RuntimeException("订单不是取消状态，不能删除！");
            }
        }
        return this.orderInfMapper.deleteOrderInf(orderInf);
    }

    /**
     * 批量删除订单信息
     *
     * @param ids 主键ID数组
     * @return
     */
    @Transactional
    public int deleteBatchOrderInf(String[] ids, String token) throws Exception {
        for (String id : ids) {
            OrderInf order = orderInfMapper.findOrderInfById(id);
            if (order != null && order.getCiState().equals("2")) {
                throw new RuntimeException("订单不是取消状态，不能删除！");
            }
        }
        return this.orderInfMapper.deleteBatchOrderInf(ids);
    }

    /**
     * 查询订单信息列表
     *
     * @param orderInf 订单信息对象
     * @return
     */
    public List<OrderInf> selectListOrderInf(OrderInf orderInf,String token)throws Exception{
       /* if(orderInf!=null && orderInf.getDatePrice()!=null && orderInf.getDispather().equals("1")){
            //通过令牌获取当前登录人员所配置的线路
            //orderInf.setDispatherLineIds();
        }*/
        if(orderInf!=null && orderInf.getDispather()!=null && orderInf.getDispather().equals("1")){
            orderInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        return  this.orderInfMapper.selectListOrderInf(orderInf);
    }

    @Override
    public List<OrderInf> selectExportListOrderInf(OrderInf orderInf, String token) throws Exception {
        if(orderInf!=null && orderInf.getDispather()!=null && orderInf.getDispather().equals("1")){
            orderInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        return  this.orderInfMapper.selectExportListOrderInf(orderInf);
    }

    public String getDispatherLineIds(String token)throws Exception{
        LineDispatchPsn lineDispatchPsn=new LineDispatchPsn();
        String suId=JwtTokenUtil.getClaimFromToken(token).getSubject();
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        lineDispatchPsn.setSuId(suId);
        List<LineDispatchPsn> listDispatchPsn= lineDispatchPsnService.selectListLineDispatchPsn(lineDispatchPsn,token);
        String lineIds="";
        for(LineDispatchPsn en:listDispatchPsn){
            lineIds+=",'"+en.getOlId()+"'";
        }
        if(lineIds.length()>1){
            lineIds=lineIds.substring(1);
        }else{
            lineIds="''";
        }
        return lineIds;
    }
    /**
     * 分页查询订单信息列表
     * @param pager 分页对象
     * @return
     */
    public  Map pageListOrderInf(Pager pager,String token) throws Exception{
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        OrderInf orderInf=(OrderInf)pager.getObj();
        if(orderInf!=null && orderInf.getDispather()!=null && orderInf.getDispather().equals("1")){
            orderInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        page.setRecords(orderInfMapper.selectListOrderInf(page,orderInf));
        List<OrderInf> list = page.getRecords();
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }

    /**
     * 同一个事务 互斥锁查询
     *
     * @param orderInf 订单信息对象
     * @return
     */
    public  List<OrderInf> selectListOrderInfForUpdate(OrderInf orderInf)throws Exception{
        return  this.orderInfMapper.selectListOrderInfForUpdate(orderInf);
    }
    /**
     * 通过主键id查询的订单信息列表
     * @param id 主键id
     * @return
     */
    public  OrderInf findOrderInfById(String id,String token)throws Exception{
        OrderInf orderInf=this.orderInfMapper.findOrderInfById(id);
        if(orderInf.getOiNewFlg().equals("1")){
            OrderInf orderInfTmp =new OrderInf();
            orderInfTmp.setOiId(id);
            orderInfTmp.setOiNewFlg("0");
            this.orderInfMapper.updateOrderInf(orderInfTmp);
        }

        return  orderInf;
    }
    /**
     * 查询锁 获取对象信息
     * @param id 主键id
     * @return
     */
    public  OrderInf findOrderInfForUpdate(String id)throws Exception{
        return  this.orderInfMapper.findOrderInfForUpdate(id);
    }
    /**
     * 查询锁 获取对象信息
     * @param qrCode 乘车码
     * @return
     */
    public  OrderInf findOrderInfByQrcodeForUpdate(String qrCode)throws Exception{
        return  this.orderInfMapper.findOrderInfByQrcodeForUpdate(qrCode);
    }

    /**
     * 乘客下单
     * @param orderInf
     * @return
     * @throws Exception
     */
    @Transactional
    public OrderInf customerAddOrderInf(OrderInf orderInf) throws Exception {
        String oiId=IdWorker.get32UUID();
        orderInf.setOiId(oiId);
        String dateFormatStr= StringUtils.remove(DateUtil.today(),"-");
        orderInf.setOiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId()+"O",dateFormatStr,6,null));
        //检查票数数量 并且扣除票数
        checkTicketAndDeduction(orderInf,null);

        //更新预下单截止时间 时间过后将扣除的票数恢复
        //未支付 设置支付有效期时间 过期将取消占票
        orderInf.setPayState("0");
        orderInf.setCiValidTime(new Date(new Date().getTime() + (Integer.parseInt(validMinuteOrder) * 60000)));
        orderInf.setOiPackageState("0");
        orderInf.setCiState("0");
        orderInf.setOiAutoPackaged("0");
        orderInf.setOiNewFlg("1");
        orderInf.setOiQrcode(String.valueOf((int)((Math.random()*9+1)*100000)));
        this.orderInfMapper.insertOrderInf(orderInf);
        return orderInf;
    }

    /**
     * 乘客下单
     * @param orderInf
     * @return
     * @throws Exception
     */
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public Result passengerOrder(OrderInf orderInf) throws Exception {
        String oiId=IdWorker.get32UUID();
        orderInf.setOiId(oiId);
        orderInf.setCreateUser("restApi");
        orderInf.setCreateTime(DateTime.now());
        String dateFormatStr= StringUtils.remove(DateUtil.today(),"-");
        orderInf.setOiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId()+"O",dateFormatStr,6,null));
        //检查票数数量 并且扣除票数
        this.checkTicketAndDeduction(orderInf,null);

        //更新预下单截止时间 时间过后将扣除的票数恢复
        //未支付 设置支付有效期时间 过期将取消占票
        orderInf.setPayState("0");
        orderInf.setCiValidTime(new Date(new Date().getTime() + (Integer.parseInt(validMinuteOrder) * 60000)));
        orderInf.setOiPackageState("0");
        orderInf.setCiState("0");
        orderInf.setOiAutoPackaged("0");
        orderInf.setOiNewFlg("1");
        orderInf.setOiQrcode(String.valueOf((int)((Math.random()*9+1)*100000)));
        int i= this.orderInfMapper.insertOrderInf(orderInf);
        if(i>0){
            List<OrderUserRelation> list=orderInf.getList();
            if(list!=null && list.size()>0){
                list.forEach(item->{
                    String uuid= IdWorker.get32UUID();
                    item.setId(uuid);
                    item.setOiId(oiId);
                });
                boolean b= this.orderUserRelationService.insertBatch(list);
                if(b){
                    Map map=new HashMap();
                    map.put("oiId",orderInf.getOiId());
                    map.put("oiCode",orderInf.getOiCode());
                    return Result.success(map);
                }
            }
        }
        return Result.error(new ErrorTip(500100,"乘客下单操作失败!"));
    }

    @Override
    public int getNewOrderNum(String token) throws Exception {
        String [] myOlId=getDispatherLineIds(token).replace("'","").split(",");
        int newOrderNum=0;
        for(String olId:myOlId){
            if(CacheKit.getKeys("globalForeverCache").contains(olId)){
                int orderNum=(Integer)CacheKit.get("globalForeverCache",olId);
                newOrderNum=newOrderNum+orderNum;
            }
        }
        return newOrderNum;
    }

    @Override
    public int clearNewOrderNum(String token) throws Exception {
        String [] myOlId=getDispatherLineIds(token).replace("'","").split(",");
        for(String olId:myOlId){
            if(CacheKit.getKeys("globalForeverCache").contains(olId)){
                CacheKit.put("globalForeverCache",olId,new Integer(0));
            }
        }
        return 0;
    }

    /**
     * 新增订单信息数据
     *
     * @param orderInf   订单信息对象
     * @param sendMsmFlg 是否给乘客发送短息
     * @return
     */
    @Transactional
    @SneakyThrows
    public int insertOrderInf(OrderInf orderInf, String token, boolean sendMsmFlg) {
        if (orderInf.getOiId() == null || orderInf.getOiId().trim().length() < 10) {
            orderInf.setOiId(IdWorker.get32UUID());
        }
        if (orderInf.getOiCode() == null || orderInf.getOiCode().trim().length() < 10) {
            String dateFormatStr = new SimpleDateFormat("yyyyMMdd").format(orderInf.getCreateTime());
            orderInf.setOiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId() + "O", dateFormatStr, 6, token));
        }
        if (orderInf.getOiDistance() == null) {
            throw new RuntimeException("订单信息中里程不能为空！");
        }

        /**车辆服务类型code 0(专)/1(快车)*/
        String ostId = orderInf.getOstId();
        if (StrUtil.isNotBlank(ostId) && StrUtil.equals("1", ostId)) {
            //检查票数数量 并且扣除票数
            checkTicketAndDeduction(orderInf, token);

            //更新预下单截止时间 时间过后将扣除的票数恢复
            //未支付 设置支付有效期时间 过期将取消占票
            if (orderInf.getPayState() == null || orderInf.getPayState().equals("0")) {
                orderInf.setCiValidTime(new Date(new Date().getTime() + (Integer.parseInt(validMinuteOrder) * 60000)));
            } else if (orderInf.getPayState() != null && orderInf.getPayState().equals("1")) {
                if (orderInf.getPayFee() == null) {
                    orderInf.setPayFee(orderInf.getCiTotalPrice());
                }
                if (orderInf.getPayTime() == null) {
                    orderInf.setPayTime(orderInf.getCreateTime());
                }
            }
            if (orderInf.getOiPackageState() == null) {
                orderInf.setOiPackageState("0");
            }
            if (orderInf.getCiState() == null) {
                orderInf.setCiState("0");
            }
            if (orderInf.getOiAutoPackaged() == null) {
                orderInf.setOiAutoPackaged("0");
            }
            if (orderInf.getOiNewFlg() == null || orderInf.getOiQrcode().trim().length() == 0) {
                orderInf.setOiNewFlg("1");
            }
            if (orderInf.getOiQrcode() == null || orderInf.getOiQrcode().trim().length() < 5) {
                orderInf.setOiQrcode(String.valueOf((int) ((Math.random() * 9 + 1) * 100000)));
            }

            this.orderInfMapper.insertOrderInf(orderInf);
            if (sendMsmFlg && orderInf.getPayState() != null && orderInf.getPayState().equals("1")) {
                OrderInf selOrderInf = orderInf;
                if (selOrderInf.getCiTel().length() > 10) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    String orderTime = sdf.format(selOrderInf.getCiSendTime());
                    if (selOrderInf.getOiOrderTimeStart() != null && selOrderInf.getOiOrderTimeEnd() != null) {
                        orderTime = sdf.format(selOrderInf.getOiOrderTimeStart()) + "-" + sdf.format(selOrderInf.getOiOrderTimeEnd());
                    }
                    Map<String, String> hmPrms = new HashMap<>();
               /* hmPrms.put("from", selOrderInf.getOiStartAddress());
                hmPrms.put("to",  selOrderInf.getOiEndAddress());*/
                    hmPrms.put("time", orderTime);
                    hmPrms.put("tel", clientHotLine);
                    AliMsgUtils.sendSmsNotice(selOrderInf.getCiTel(), "SMS_153330987", hmPrms);
                }
            }
        } else {
            /**专车执行逻辑*/
            PreOrderInf pre = PreOrderInf.class.newInstance();
            BeanUtil.copyProperties(orderInf, pre, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreCase(true));
            boolean b = pre.insert();
            if (b) {
                if (sendMsmFlg && StrUtil.equals("1", pre.getPayState())) {
                    if (StringUtils.length(pre.getCiTel()) > 10) {
                        Map<String, String> map = Maps.newHashMap();
                        map.put("time", DateUtil.formatDateTime(DateTime.now()));
                        map.put("tel", clientHotLine);
                        AliMsgUtils.sendSmsNotice(pre.getCiTel(), "SMS_153330987", map);
                    }
                }
            }
        }
        return 0;
    }

    /**
     * 买票 占座
     *
     * @param orderInf
     * @param token
     * @throws Exception
     */
    private void checkTicketAndDeduction(OrderInf orderInf, String token) throws Exception {

        int num = orderInf.getCiNum();
        if (num < 1) {
            throw new RuntimeException("乘车人数必须大于等于1！");
        }
        //获取线路信息 查看是否设置了按照班次发车
        VehiclePriceType tmpVehiclePriceType = new VehiclePriceType();
        tmpVehiclePriceType.setVptCode(orderInf.getVptCode());
        List<VehiclePriceType> list = vehiclePriceTypeService.selectListVehiclePriceType(tmpVehiclePriceType, token);
        if (list == null || list.size() == 0) {
            throw new RuntimeException("车型未找到！");
        }
        tmpVehiclePriceType = list.get(0);
        if (tmpVehiclePriceType.getCvpSeatNum() < orderInf.getCiNum()) {
            throw new RuntimeException("人数不能超过" + tmpVehiclePriceType.getCvpSeatNum() + "！");
        }

        String olId = orderInf.getOlId();
        //检查预下单时间
        OrderLine oline = orderLineService.findOrderLineById(olId, token);
        if (oline == null) {
            throw new RuntimeException("未找到线路！");
        }
        Date sendDate = orderInf.getCiSendTime();
        int preSaleTime = oline.getOlPreSaleMinitue();
        long minTime = new Date().getTime() + (preSaleTime * 1000 * 60);
        if (sendDate.getTime() <= minTime) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            throw new RuntimeException("亲，您只能安排" + dateFormat.format(new Date(minTime)) + "以后的行程！");
        }

        if (orderInf.getOstId().equals("0")) {//专车不用扣票
            return;
        }
        //检查余票
        if (oline.getOlSendByTimer().equals("1")) {
            LineTimeSlot lineTimeSlot = new LineTimeSlot();
            lineTimeSlot.setLtsDate(sendDate);
            lineTimeSlot.setOlId(olId);
            lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
            List<LineTimeSlot> listLineTimeSlot = lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
            if (listLineTimeSlot != null && listLineTimeSlot.size() > 0) {
                lineTimeSlot = listLineTimeSlot.get(0);
                if (lineTimeSlot.getLtsMaxNum() > 0) {//限制购票数量
                    if ((lineTimeSlot.getLtsMaxNum() - lineTimeSlot.getLtsSaleNum()) < num) {
                        throw new RuntimeException("该时段预留人数不足，请修改人数或选择其他时段！");
                    }
                    lineTimeSlot.setLtsSaleNum(num);
                    lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot, token);
                } else if (lineTimeSlot.getLtsMaxNum() == 0) {
                    throw new RuntimeException("该时段预留人数不足，请修改人数或选择其他时段！");
                }
            } else {
                throw new RuntimeException("未找到匹配的班次！");
            }
        }
    }

    /**
     * 取消 恢复占用的票数
     *
     * @param orderInf
     * @param token
     */
    private void cancelTicketSalNum(OrderInf orderInf, String token) throws Exception {
        if (orderInf.getOstId().equals("0")) {//专车不用扣票
            return;
        }
        int num = orderInf.getCiNum();
        String olId = orderInf.getOlId();
        //检查预下单时间
        OrderLine oline = orderLineService.findOrderLineById(olId, token);
        if (oline == null) {
            throw new RuntimeException("未找到线路！");
        }
        Date sendDate = orderInf.getCiSendTime();
        if (oline.getOlSendByTimer().equals("1")) {
            LineTimeSlot lineTimeSlot = new LineTimeSlot();
            lineTimeSlot.setLtsDate(sendDate);
            lineTimeSlot.setOlId(olId);
            lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
            List<LineTimeSlot> listLineTimeSlot = lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
            if (listLineTimeSlot != null && listLineTimeSlot.size() > 0) {
                lineTimeSlot = listLineTimeSlot.get(0);
                if (lineTimeSlot.getLtsSaleNum() >= num) {//限制购票数量
                    lineTimeSlot.setLtsSaleNum(-1 * num);
                } else {
                    lineTimeSlot.setLtsSaleNum(-1 * lineTimeSlot.getLtsSaleNum());
                }
                lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot, token);
            } else {
                throw new RuntimeException("未找到匹配的班次！");
            }
        }
    }

    /**
     * 更新订单信息数据
     *
     * @param orderInf 订单信息对象
     * @return
     */
    @SneakyThrows(value = Throwable.class)
    @Transactional(rollbackFor = Exception.class)
    public int updateOrderInf(OrderInf orderInf, String token) throws Exception {
        //修改状态为已支付
        OrderRefundInf ori=OrderRefundInf.class.newInstance();
        ori.setOrState(orderInf.getKey());
        Map<String, String> map = new HashMap();
        if (orderInf.getPayState() != null && orderInf.getPayState().equals("1")) {
            OrderInf selOrderInf = this.findOrderInfForUpdate(orderInf.getOiId());
            if (selOrderInf == null) {
                throw new RuntimeException("未找到订单！");
            }
            if (selOrderInf.getPayState().equals("0")) {
                //加入新订单列表中
                String olId = selOrderInf.getOlId();
                if (CacheKit.getKeys("globalForeverCache").contains(olId)) {
                    int newOrderNum = (Integer) CacheKit.get("globalForeverCache", olId);
                    newOrderNum = newOrderNum + 1;
                    CacheKit.put("globalForeverCache", olId, new Integer(newOrderNum));
                } else {
                    CacheKit.put("globalForeverCache", olId, new Integer(1));
                }

                //发送短信通知乘客下单成功
                if (selOrderInf.getCiTel().length() > 10) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    String orderTime = sdf.format(selOrderInf.getCiSendTime());
                    if (selOrderInf.getOiOrderTimeStart() != null && selOrderInf.getOiOrderTimeEnd() != null) {
                        orderTime = sdf.format(selOrderInf.getOiOrderTimeStart()) + "-" + sdf.format(selOrderInf.getOiOrderTimeEnd());
                    }
                    Map<String, String> hmPrms = new HashMap<String, String>();
                   /* hmPrms.put("from", selOrderInf.getOiStartAddress());
                    hmPrms.put("to",  selOrderInf.getOiEndAddress());*/
                    hmPrms.put("time", orderTime);
                    hmPrms.put("tel", clientHotLine);
                    AliMsgUtils.sendSmsNotice(selOrderInf.getCiTel(), "SMS_153330987", hmPrms);
                }
                /***处理与处理单信息*/
                String ostId = orderInf.getOlId();
                if (StringUtils.isNotBlank(ostId)) {
                    if (StringUtils.equals("0", ostId)) {
                        String id = orderInf.getOiId();
                        Wrapper<PreOrderInf> wrapper = new EntityWrapper<PreOrderInf>();
                        wrapper.eq("oi_id", id);
                        wrapper.last("limit 1");
                        PreOrderInf preOrderInf = this.preOrderInfService.selectOne(wrapper);
                        if (preOrderInf != null) {
                            preOrderInf.setPayState("1");
                            preOrderInf.setPayTime(DateTime.now());
                            preOrderInf.setPayFee(orderInf.getPayFee());
                            preOrderInf.updateById();
                        } else {
                            throw new RuntimeException("不存在预处理订单，请检查!!!");
                        }
                    }
                }
                return this.orderInfMapper.updateOrderInfPayState(orderInf);
            }
        }
        if (orderInf.getCiState() != null && orderInf.getCiState().equals("2")) {//取消订单
            OrderInf selOrderInf = this.findOrderInfForUpdate(orderInf.getOiId());
            if (selOrderInf == null) {
                throw new RuntimeException("未找到订单！");
            }

            if ( !selOrderInf.getCiState().equals("0")) {
                throw new RuntimeException("未乘车状态，不能修改！");
            }
            //数据库数据订单状态不是取消状态，不是取消状态 取消占座 修改取消
            if (selOrderInf.getCiState() != null && !selOrderInf.getCiState().equals("2")) {
                //恢复订单的票数
                cancelTicketSalNum(selOrderInf, token);
                //更新订单状态为已经取消 并且更新站票有效时间为null
            }
            //取消订单退款
            int i = this.orderInfMapper.updateOrderInfCustomStateCancel(orderInf);
            if (i > 0) {
                orderInf = this.orderInfMapper.selectById(orderInf.getOiId());
                if (orderInf.getPayState().equals("1")) {
                    /**发起退款申请
                     *(1):指派前           => 可取消，退款100%；
                     *(2):指派后 && > 2小时 => 可取消，退款（实际支付金额）50%；
                     *(3):指派后 && < 2小时 => 不可取消，退款（实际支付金额）0%
                     * */
                    String oiId = orderInf.getOiId();
                    ori.setOiId(oiId);
                    String total_fee = String.valueOf(orderInf.getPayFee().intValue());
                    String refund_fee = String.valueOf(orderInf.getPayFee().intValue());
                    /**条件退款*/
                    if (StringUtils.equals("1", reType)) {
                        Wrapper<TaskOrder> taskOrderWrapper = new EntityWrapper<>();
                        taskOrderWrapper.eq("oi_id", oiId);
                        taskOrderWrapper.last("limit 1");
                        final TaskOrder taskOrder = this.taskOrderService.selectOne(taskOrderWrapper);
                        if (taskOrder != null) {
                            ShiroUser user= ShiroKit.getUser();
                            ori.setCreateTime(DateTime.now());
                            if(ObjectUtil.isNotNull(user)) {
                                ori.setCreateUser(user.getAccount());
                            }else {
                                ori.setCreateUser("restApi");
                            }
                            ori.setOiId(oiId);
                            Wrapper<TaskInf> wrapper = new EntityWrapper<>();
                            wrapper.eq("ti_id", taskOrder.getTiId());
                            /**取未乘车 与 已乘车任务列表*/
                            wrapper.and().eq("ti_state", "1");
                            wrapper.last("limit 1");
                            TaskInf taskInf = taskInfService.selectOne(wrapper);
                            /**已指派*/
                            if (taskInf != null) {
                                /***预约开始时间*/
                                final Date tiTaskGetTime = orderInf.getOiOrderTimeStart();
                                final Date now = DateTime.now();
                                if(tiTaskGetTime!=null){
                                    long diff = DateTimeKit.diff(tiTaskGetTime, now, 3600 * 1000L);
                                    /**大于两小时 退款50%*/
                                    if(diff>=2){
                                        total_fee = String.valueOf(Integer.valueOf(total_fee)/2);
                                        refund_fee = String.valueOf(Integer.valueOf(refund_fee)/2);
                                    }else{
                                        /**两小时以内  不退款 抛异常结束*/
                                        total_fee = String.valueOf(0);
                                        refund_fee = String.valueOf(0);
                                        throw new RuntimeException("指派两小时内不可退款!");
                                    }
                                }
                                ori.setOrRefundFee(Integer.parseInt(total_fee));
                                ori.setRefundTime(DateTime.now());
                            }else{
                                /***未指派 全退*/
                                ori.setCreateUser("restApi");
                                ori.setCreateTime(DateTime.now());
                                ori.setOrRefundFee(Integer.parseInt(total_fee));
                                ori.setRefundTime(DateTime.now());
                                ori.setRemark("全额退款");
                            }
                        }else{
                            //未打包 全额退款
                            ori.setCreateUser("restApi");
                            ori.setCreateTime(DateTime.now());
                            ori.setOrRefundFee(Integer.parseInt(total_fee));
                            ori.setRefundTime(DateTime.now());
                            ori.setRemark("全额退款");
                        }
                    }else{
                        /**全额退款*/
                        ori.setCreateUser("restApi");
                        ori.setCreateTime(DateTime.now());
                        ori.setOrRefundFee(Integer.parseInt(total_fee));
                        ori.setRefundTime(DateTime.now());
                        ori.setRemark("全额退款");
                    }
                    OkHttpClient client = new OkHttpClient();
                    FormBody.Builder formBody = new FormBody.Builder();
                    formBody.add("method", this.method);
                    formBody.add("out_trade_no", oiId);
                    formBody.add("out_refund_no", IdUtil.simpleUUID());
                    formBody.add("total_fee", total_fee);
                    formBody.add("refund_fee", refund_fee);
                    Request request = new Request.Builder().url(this.REFUND_URL).post(formBody.build()).build();
                    client.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            msg.set("出错信息:"+e.getMessage());
                            log.error("调用退款接口IO通讯报错,出错信息:{}", e.getMessage());
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            /***回调的方法执行在子线程*/
                            if (response.isSuccessful()) {
                                String res = response.body().string();
                                cn.hutool.json.JSONObject object = JSONUtil.parseObj(res);
                                String status = (String) object.get("status");
                                map.put("status", status);
                                if (StringUtils.isNotBlank(status) && StringUtils.equals(status, "200")) {
                                    boolean b = refund(oiId);
                                    if(b) {
                                        ori.setState("1");
                                        ori.setRemark("退款成功");
                                    }else{
                                        ori.setState("0");
                                        ori.setRemark("退款失败,失败原因:"+msg.get());
                                    }
                                    boolean bb=ori.insert();
                                    if(bb){
                                        log.info("退款发起插入{}成功", JSONObject.toJSONString(ori));
                                    }else{
                                        log.error("退款发起插入{}失败", JSONObject.toJSONString(ori));
                                    }
                                } else {
                                    String msg = (String) object.get("err_msg");
                                    map.put("msg", msg);
                                }
                            }
                        }
                    });
                }
            }
        }else if(orderInf.getCiState()!=null && orderInf.getCiState().equals("0")){//恢复取消订单
            OrderInf selOrderInf=this.findOrderInfForUpdate(orderInf.getOiId());
            if(selOrderInf==null){
                throw new RuntimeException("未找到订单！");
            }
            //将取消订单修改成正常订单
            if(selOrderInf.getCiState().equals("2")){
                //检查并且占票
                checkTicketAndDeduction(selOrderInf,token);
                orderInf.setCiValidTime(new Date(new Date().getTime() +( Integer.parseInt(validMinuteOrder)*60000)));
                orderInfMapper.updateOrderInfCustomStateRestCancel(orderInf);
            }else{
                this.orderInfMapper.updateOrderInf(orderInf);
            }
        }else{
            this.orderInfMapper.updateOrderInf(orderInf);
        }
        return 0;
    }

    public Boolean refund(@RequestParam(value = "oiid", required = true) String oiid) {
        try {
            log.debug("oiid:" + oiid);
            OrderInf orderInf = this.orderInfMapper.findOrderInfById(oiid);
            if (orderInf != null) {
                orderInf.setPayState("3");
                return  orderInf.updateById();
            }
        } catch (Exception e) {
            msg.set("出错信息:"+e.getMessage());
            log.error("修改订单信息失败，失败原因:{}",e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 查询订单信息返回key-Value属性
     *
     * @param orderInf 系统操作对象
     * @return
     */
    @SneakyThrows
    public List<CommonKeyValue> optionsOrderInf(OrderInf orderInf, String token) {
        List<OrderInf> listOrderInf = this.orderInfMapper.selectListOrderInf(orderInf);
        List<CommonKeyValue> listOptions = new ArrayList<CommonKeyValue>();
        listOrderInf.stream().forEach(x -> {
            CommonKeyValue opts = new CommonKeyValue();
            opts.setId("" + x.getOiId());
            opts.setValue(x.getOlName());
            listOptions.add(opts);

        });
        return listOptions;
    }

    /**
     * 乘客上车 将乘客状态变成已上车，并且更新上车时间 上车位置 上车坐标
     *
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfUp(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null || orderInf.getOiId() == null || orderInf.getOiId().length() < 10) {
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfUp(orderInf);
        return 0;
    }

    /**
     * 恢复上车 将上车时间 上车地点 上车坐标置空标
     *
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfRegainUp(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null || orderInf.getOiId() == null || orderInf.getOiId().length() < 10) {
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfRegainUp(orderInf);
        return 0;
    }

    /**
     * 乘客下车 将乘客状态变成已下车，并且更新下车时间 下车位置 下车坐标
     *
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfDown(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null || orderInf.getOiId() == null || orderInf.getOiId().length() < 10) {
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfDown(orderInf);
        return 0;
    }

    /**
     * 恢复下车 将下车时间 下车地点 下车坐标置空
     *
     * @param orderInf
     * @param token    令牌
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfRegainDown(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null || orderInf.getOiId() == null || orderInf.getOiId().length() < 10) {
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfRegainDown(orderInf);
        return 0;
    }

    /**
     * 更新乘客状态
     *
     * @param orderInf
     * @param token    令牌
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfCustomState(OrderInf orderInf, String token) throws Exception {
        if (orderInf == null || orderInf.getCiState() == null || orderInf.getOiId() == null || orderInf.getOiId().length() < 10
                || !(orderInf.getCiState().equals("0") || orderInf.getCiState().equals("1") || orderInf.getCiState().equals("2") || orderInf.getCiState().equals("3"))) {
            new RuntimeException("参数不全!");
        }
        if (orderInf.getCiState().equals("2") || orderInf.getCiState().equals("0")) {
            updateOrderInf(orderInf, token);
        }
        return 0;
    }

    @Transactional
    public void scheduleClearTicket() throws Exception {
        //查询过期未付款的订单
        List<OrderInf> listOrderInf = this.orderInfMapper.selectListOrderInfForClearTicket();
        for (OrderInf item : listOrderInf) {
            OrderInf orderInf = this.findOrderInfForUpdate(item.getOiId());
            if (!(orderInf.getPayState().equals("0") && orderInf.getCiState().equals("0") && orderInf.getOiPackageState().equals("0") //未打包 //未支付 //未乘车
                    && orderInf.getOstId().equals("1") //快车
                    && orderInf.getCiValidTime() != null && orderInf.getCiValidTime().compareTo(new Date()) < 0)) {//支付时间已过
                continue;
            }
            int num = orderInf.getCiNum();
            //取消占座
            LineTimeSlot lineTimeSlot = new LineTimeSlot();
            lineTimeSlot.setLtsDate(orderInf.getCiSendTime());
            lineTimeSlot.setOlId(orderInf.getOlId());
            lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
            List<LineTimeSlot> listLineTimeSlot = lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
            if (listLineTimeSlot != null && listLineTimeSlot.size() > 0) {
                lineTimeSlot = listLineTimeSlot.get(0);
                if (lineTimeSlot.getLtsSaleNum() >= num) {//限制购票数量
                    lineTimeSlot.setLtsSaleNum(-1 * num);
                } else {
                    lineTimeSlot.setLtsSaleNum(-1 * lineTimeSlot.getLtsSaleNum());
                }
                lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot, "");
            }
            //更细订单为取消状态
            this.orderInfMapper.updateOrderInfCustomStateCancel(orderInf);
        }
    }
}
